home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / S / GEM / GEMENV.D < prev    next >
Encoding:
Modula Definition  |  1990-12-01  |  21.0 KB  |  508 lines

  1. DEFINITION MODULE GEMEnv;
  2.  
  3.  
  4. (*      Megamax Modula-2 GEM Library: Diverse Kontrollfunktionen
  5.  *
  6.  *      Autor: Manuel Chakravarty       Erstellt: März-Oktober 1987
  7.  *
  8.  *      Version 2.2     V#0062
  9.  *)
  10.  
  11. (*      Mit den Routinen dieses Moduls kann sich eine Anwendung beim GEM
  12.  *      An- und Abmelden, außerdem erfolgt hier die Anmeldung weiterer
  13.  *      VDI-Geräte.
  14.  *)
  15.  
  16.  
  17. FROM GrafBase IMPORT Point, Rectangle;
  18.  
  19. FROM GEMGlobals IMPORT TEffectSet;
  20.  
  21.  
  22.                         (*  Kontroll Funktionen  *)
  23.                         (*  ===================  *)
  24.                 
  25.                 
  26. TYPE    GemHandle;      (*  Dient zur Identifizierung einer kompletten
  27.                          *  Anmeldung (per 'InitGem') beim GEM.
  28.                          *  (GEM-Referenz)
  29.                          *)
  30.  
  31.         DeviceHandle;   (*  Dient zur Identifizierung eines VDI-Gerätes.
  32.                          *  Siehe auch 'OpenDevice'. (Geräte-Referenz)
  33.                          *)
  34.                          
  35.                          
  36. CONST   NoDevice        = DeviceHandle (NIL);   (* Wert für ein nicht besetz-
  37.                                                  * tes Geräte-handle
  38.                                                  *)
  39.  
  40.         NDC             = 0;             (*  Normalisierte Koordinaten  *)
  41.         RC              = 2;             (*  Raster Koordinaten  *)
  42.  
  43.  
  44. PROCEDURE InitGem (    sysKoor: CARDINAL;
  45.                    VAR handle : DeviceHandle;
  46.                    VAR success: BOOLEAN);
  47.  
  48.         (*  Anmeldung einer Application beim GEM und Eröffnen einer
  49.          *  virtuellen Bildschirmarbeitsstation.
  50.          *
  51.          *  'sysKoor' -- Bestimmt das zu benutzenden Koordinatensystem,
  52.          *               dabei steht 'RC' für Rasterkoordinaten und NDC
  53.          *               für normalisierte Koordinaten.
  54.          *  'handle'  -- Liefert die Gerätereferenz der virtuellen Bild-
  55.          *               schirmarbeitsstation. Diese Referenz muß bei
  56.          *               jedem VDI-Aufruf als erster Parameter angege-
  57.          *               ben werden.
  58.          *  'success' -- Meldet ob die Anmeldung erfolgreich verlaufen
  59.          *               ist. Ist dies nicht der Fall, so ist auch der
  60.          *               Wert von 'handle' ungültig.
  61.          *
  62.          *  Ein Aufruf dieser Prozedur sollte am Anfang jeder Benutzung
  63.          *  der GEM Bibliothek stehen. Wird er nicht durchgeführt, so
  64.          *  kann es zum Absturz des Systems kommen.
  65.          *  Alternativ kann aber, wenn keine VDI-Funktionen benötigt
  66.          *  werden, 'InitApplication' (s.u.) aufgerufen werden.
  67.          *
  68.          *  Falls die Prozedur 'GemActive' den Wert 'TRUE' liefert,
  69.          *  sind AES-Aufruf ohne jede Vorbereitung und VDI-Aufruf nach
  70.          *  dem Erzeugen einer (virtuellen) Arbeitstation mit 'OpenDevice'
  71.          *  ohne Benutzung von 'InitGem' möglich. Doch sollte
  72.          *  diese Vorgehensweise nur in Ausnahmefällen gewählt werden,
  73.          *  da dann z.B. keine autom. Abmeldung von Fenstern u.ä. bei
  74.          *  Prozessende durchgeführt wird.
  75.          *
  76.          *  Die Variablen des Moduls 'PathEnv' werden zudem initialisiert:
  77.          *
  78.          *  'HomePath' wird in der Regel mit dem Pfad besetzt, von dem dies
  79.          *  Programm stammt. Dies erlaubt dann z.B. die Verwendung von '*'
  80.          *  (HomeSymbol) in Pfadlisten für 'Paths.SearchFile'. Siehe dazu
  81.          *  die Hinweise im PathEnv-Modul!
  82.          *
  83.          *  'SelectFile' erhält je nach GEM-Version die Funktion 'SelectFile'
  84.          *  bzw. 'SelectFileExtended' aus dem Modul 'AESMisc' zugewiesen.
  85.          *
  86.          *  ACHTUNG: Alle bisherigen GEM Versionen unterstützen nur
  87.          *           Rasterkoordinaten um normalisierte Koordinaten
  88.          *           benutzen zu können, muß das GDOS geladen werden.
  89.          *)
  90.  
  91. PROCEDURE GemActive (): BOOLEAN;
  92.  
  93.         (*  Erfragt, ob ein anderes Modul schon einen 'InitGem'- oder
  94.          *  'InitApplication'-Aufruf getätigt hat, d.h. ob ein benutz-
  95.          *  barer 'GemHandle' vorhanden ist. (Siehe auch 'InitGem')
  96.          *)
  97.  
  98. PROCEDURE ExitGem (VAR handle: GemHandle);
  99.  
  100.         (*  Dient zum Abmelden einer Application beim GEM.
  101.          *
  102.          *  Es werden autom. alle noch offenen Fenster geschlossen, alle
  103.          *  angemeldeten Geräte beim VDI abgemeldet und eventuell noch
  104.          *  nicht rückgänig gemachte 'HideCursor', 'WindowUpdate' etc.
  105.          *  Aufrufe zurückgesetzt.
  106.          *  Sobald ein Modul terminiert wird für jedes auf dieser Modul-
  107.          *  ebene durchgeführten 'InitGem', welches noch nicht rückgängig
  108.          *  gemacht wurde, ein 'ExitGem' durchgeführt, dies gilt insbe-
  109.          *  sondere für Laufzeitfehler.
  110.          *)
  111.  
  112.  
  113. PROCEDURE InitApplication (VAR success: BOOLEAN);  (* "appl_init" *)
  114.  
  115.         (*  Wie 'InitGem', jedoch werden weder eine virtuelle "Workstation"
  116.          *  mit 'OpenDevice' geöffnet, noch die PathEnv-Variablen initiali-
  117.          *  siert. Diese Funktion kann statt 'InitGem' aufgerufen werden,
  118.          *  wenn keine VDI-Funktionen benutzt werden. Dies ist beispielsweise
  119.          *  bei vielen Accessories der Fall. Die Abmeldung kann mit
  120.          *  'ExitGem (gemHandle)', wobei 'gemHandle' die mit 'CurrGemHandle'
  121.          *  erfragte Referenz enthalten muß oder mit 'ExitApplication'
  122.          *  durchgeführt werden.
  123.          *)
  124.  
  125. PROCEDURE ExitApplication ();  (* "appl_exit" *)
  126.  
  127.         (*  Abmeldung der mit 'InitApplication' durchgeführten AES-Anmeldung.
  128.          *)
  129.  
  130.  
  131. PROCEDURE GrafHandle (VAR charW, charH,
  132.                           cellW, cellH: CARDINAL;
  133.                       VAR hdl         : CARDINAL);
  134.  
  135.         (*  Ermittelt die VDI-Referenz, welche das AES bei seinem 'Open
  136.          *  Workstation' Aufruf erhalten hat. Zusätzlich werden noch die
  137.          *  Ausmaße eines Zeichens des Systemzeichensatzes zurückgegeben.
  138.          *
  139.          *  'charW', 'charH',
  140.          *  'cellW', 'cellH'  -- Ausmaße eines Zeichens des Systemzeichen-
  141.          *                       satzes.
  142.          *  'hdl'             -- VDI-Referenz des AES. Hiermit kann man
  143.          *                       mit 'OpenDevice' weitere virtuelle Bild-
  144.          *                       schirmarbeitsstationen eröffnen.
  145.          *
  146.          *  ACHTUNG: Die Werte von 'charW', 'charH', 'cellW', cellH'
  147.          *           werden vom GEM nicht korrekt geliefert. Daher
  148.          *           ist von ihrer Verwendung abzuraten.
  149.          *)
  150.  
  151.  
  152. CONST   NonVirtual      = 0;    (*  Gerät soll mit Open Workstation geöffnet
  153.                                  *  werden.
  154.                                  *)
  155.  
  156. PROCEDURE OpenDevice (dev, sysKoor, mode: CARDINAL; VAR hdl: DeviceHandle);
  157.  
  158.         (*  Dient zum Öffnen einer (virtuellen) Arbeitsstation.
  159.          *
  160.          *  Eingabeparameter:
  161.          *  -----------------
  162.          *
  163.          *  'dev'     -- Gibt das zu öffnende Gerät an. Entspricht der
  164.          *               in 'ASSIGN.SYS' angegebenen Gerätenummer.
  165.          *  'sysKoor' -- Bestimmt das zu benutzenden Koordinatensystem,
  166.          *               dabei steht 'RC' für Rasterkoordinaten und NDC
  167.          *               für normalisierte Koordinaten.
  168.          *  'mode'    -- Wird hier 'NonVirtual' angegeben, so wird ein
  169.          *               eine neue Arbeitsstation eröffnet. Wird aber
  170.          *               das VDI-Handle einer Arbeitsstation (z.B. mit
  171.          *               'GrafHandle' ermittelt) übergeben, so wird zu
  172.          *               dieser Arbeitsstation eine virtuelle Arbeits-
  173.          *               station geöffnet.
  174.          *
  175.          *  Ausgabeparameter:
  176.          *  -----------------
  177.          *
  178.          *  'hdl'     -- Die neue Gerätereferenz. Sie muß bei jedem VDI-
  179.          *               Aufruf, der an dieses Gerät gehen soll als erster
  180.          *               Parameter übergeben werden.
  181.          *
  182.          *  ACHTUNG: Das Öffnen weitere nicht virtueller Arbeitsstationen
  183.          *           ist nur mit geledenem GDOS möglich.
  184.          *)
  185.          
  186. PROCEDURE CloseDevice (handle: DeviceHandle);
  187.  
  188.         (*  Die (virtuelle) Arbeitsstation wird geschlossen.
  189.          *
  190.          *  Bei einem Aufruf von 'ExitGem', werden alle Geräte, die unter
  191.          *  dem abgemeldeten 'GemHandle' geöffnet wurden autom. geschlossen.
  192.          *)
  193.          
  194.         
  195. TYPE    GDPAttribute = (lineOp, markerOp, textOp, fillOp, noAttribute,
  196.                         notAvaible);
  197.         GDPFkt       = (barGDP, arcGDP, pieGDP, circleGDP, ellipseGDP,
  198.                         eArcGDP,  ePieGDP, rRectGDP, fRectGDP, jTextGDP);
  199.         InputDev     = (keybd, other);
  200.         DeviceType   = (outDev, inDev, inoutDev, reservedDev, metafile);
  201.         ScreenType   = (noScreen, difCtrlDifScrn, difCtrlSamScrn,
  202.                         samCtrlDifMem, samCtrlSamMem);
  203.         TextRotType  = (noTextRot, step90, everyDirec);
  204.         
  205.         PtrDevParm   = POINTER TO DevParm;
  206.         DevParm      = RECORD
  207.         
  208.                          (*  Diese 4 Werte entsprechen den von
  209.                           *  'GrafHandle' gelieferten Werten.
  210.                           *)
  211.                          charWidth, charHeight,
  212.                          cellWidth, cellHeight,
  213.                          
  214.                          (*  Breite und Höhe des Pixelrasters
  215.                           *  [0..rasterWidth] und [0..rasterHeight]
  216.                           *)
  217.                          rasterWidth, rasterHeight,
  218.                          
  219.                          (*  Breite und Höhe eines Pixels in mm/1000
  220.                           *)
  221.                          pointWidth, pointHeight,
  222.                          
  223.                          (*  Anzahl der Schriftgrößen (0 bed. kontinuierlich)
  224.                           *)
  225.                          fontSizes,
  226.                          
  227.                          (*  Anzahl der Linienarten und -stärken
  228.                           *  (bei Letzterem bedeutet 0 kontinuierlich)
  229.                           *)
  230.                          lTypes, lWidths,
  231.                          
  232.                          (*  Anzahl der Makierungsarten und -größen
  233.                           *  (bei Letzterem bedeutet 0 kontinuierlich)
  234.                           *)
  235.                          mTypes, mSizes,
  236.                          
  237.                          (*  Anzahl der verfügbaren Zeichensätze
  238.                           *)
  239.                          fonts,
  240.                          
  241.                          (*  Anzahl der Füllmuster und Schraffuren
  242.                           *)
  243.                          fPatterns, fHatchings,
  244.                          
  245.                          (*  Anzahl der gleichzeitig darstellbaren Farben
  246.                           *)
  247.                          noColors,
  248.                          
  249.                          (*  Minimale und maximale Zeichenbreite und -höhe
  250.                           *)
  251.                          minWChar, maxWChar,
  252.                          minHChar, maxHChar,
  253.                          
  254.                          (*  Minimale und maximale Zeilenbreite
  255.                           *)
  256.                          minWRow, maxWRow,
  257.                          
  258.                          (*  Minimale und maximale Breite und Höhe
  259.                           *  von Makierungen
  260.                           *)
  261.                          minWMark, maxWMark,
  262.                          minHMark, maxHMark,
  263.                          
  264.                          (*  Anzahl der verfügbaren Hintergrundfarben
  265.                           *)
  266.                          bgColors,
  267.                          
  268.                          (*  Anzahl der Farbebenen (planes)
  269.                           *)
  270.                          maxRasterPls,
  271.                          
  272.                          (*  Anzahl der 16x16 Pixel Rasteroperationen pro sec.
  273.                           *)
  274.                          op16PerSec,
  275.                          
  276.                          (*  Anzahl der Schreibmodi
  277.                           *)
  278.                          noWrtModes,
  279.                          
  280.                          (*  Höchster Eingabemodus (0 ~ keine Eingabe,
  281.                           *  1 ~ Nachfragemodus, 2 ~ Testmodus)
  282.                           *)
  283.                          maxInMode,
  284.                          
  285.                          (*  Maximale Anzahl von Punkten in einem
  286.                           *  Punkte-Array und maximale Anzahl von
  287.                           *  Zeichen in einem Zeichen-Array
  288.                           *)
  289.                          maxMarker, maxStrLen,
  290.                          
  291.                          (*  Anzahl der Mausknöpfe
  292.                           *)
  293.                          noMButts,
  294.                          
  295.                          (*  Anzahl der Zeichenmodi für verbreiterte Linien
  296.                           *)
  297.                          thickLnModes : CARDINAL;
  298.                          
  299.                          (*  Gibt die verfügbaren grafischen
  300.                           *  Grundfunktionen an
  301.                           *)
  302.                          possibleGDPs : ARRAY GDPFkt OF GDPAttribute;
  303.                          
  304.                          (*  Folgende Flags bestimmen ob gewisse
  305.                           *  Operationen mit dem beschriebenen
  306.                           *  Gerät möglich sind und zwar:
  307.                           *)
  308.                          color,         (*  Farbe                       *)
  309.                          fill,          (*  Füllmuster                  *)
  310.                          cArray,        (*  Cell-Arrays                 *)
  311.                          zooming,       (*  Skalierung von Rastern      *)
  312.                          lookUpTab,     (*  Color Look Up Table (CLUT)  *)
  313.                          textJust,      (*  Textausrichtung             *)
  314.                          contFill,      (*  contour fill                *)
  315.                          penChange,     (*  Plotterstift austauschen    *)
  316.                          colorRibbon,   (*  Farbband (Drucker)          *)
  317.                          thickLnTyps    (*  verbreiterte Linientypen    *)
  318.                                       : BOOLEAN;
  319.                          
  320.                          (*  Folgende Variable bestimmen das Eingabegerät
  321.                           *  für diverse Arten der Eingabe und zwar für:
  322.                           *)
  323.                          grafCCtrl,     (*  grafische Eingaben        *)
  324.                          valueIn,       (*  Werteingaben              *)
  325.                          caseIn,        (*  Auswahleingaben           *)
  326.                          alphanumIn     (*  alphanumerische Eingaben  *)
  327.                                       : InputDev;
  328.                          
  329.                          (*  Typ des beschriebenen Gerätes
  330.                           *)
  331.                          deviceType   : DeviceType;
  332.                          
  333.                          (*  Art des Bildschirms
  334.                           *)
  335.                          screen       : ScreenType;
  336.                          
  337.                          (*  Unterstützte Texteffekte
  338.                           *)
  339.                          useTEffects  : TEffectSet;
  340.                          
  341.                          (*  Art der unterstützten Textrotation
  342.                           *)
  343.                          textRot      : TextRotType;
  344.                          
  345.                        END;
  346.      
  347. PROCEDURE DeviceParameter (handle: DeviceHandle): PtrDevParm;
  348.  
  349.         (*  Liefert die Geräteparameter eines geöffneten Gerätes.
  350.          *
  351.          *  'handle' -- Gerätereferenz des Gerätes von dem die Parameter
  352.          *              ermittelt werden sollen.
  353.          *)
  354.  
  355.  
  356. PROCEDURE CurrGemHandle (): GemHandle;
  357.  
  358.         (*  Ermittelt die aktuelle GEM-Referenz ('GemHandle').
  359.          *)
  360.  
  361. PROCEDURE SetCurrGemHandle (handle: GemHandle; VAR success: BOOLEAN);
  362.  
  363.         (*  Setzt die aktuelle GEM-Refrenz.
  364.          *
  365.          *  'handle'  -- Neu zu setzende GEM-Referenz.
  366.          *  'success' -- Wird hier 'FALSE' geliefert, so ist 'handle'
  367.          *               keine gültige GEM-Referenz und die aktuelle
  368.          *               Refrenz wurde nicht verändert.
  369.          *)
  370.          
  371.  
  372.                         (*  Fehlerbehandlung  *)
  373.                         (*  ================  *)
  374.  
  375. VAR     ErrorProc: PROC;
  376.  
  377. PROCEDURE GemError (): BOOLEAN;
  378.  
  379.         (*  Ermittelt, ob beim letzten Aufruf einer GEM-Routine ein
  380.          *  Fehler aufgetretten ist.
  381.          *
  382.          *  Tritt ein Fehler auf, der nicht mittels dieser Prozedur
  383.          *  erfragt wird, so ruft die GEM-Bibliothek beim nächsten
  384.          *  Aufruf einer GEM-Routine die Prozedur 'ErrorProc' auf.
  385.          *  Ist letztere von der Applikation nicht verändert worden,
  386.          *  so wird die Modula-Standardprozedur 'HALT' aufgerufen.
  387.          *)
  388.  
  389. PROCEDURE ErrorNumber (): INTEGER;
  390.  
  391.         (*  Ermittelt im Fehlerfall den Fehler auslösenden Wert.
  392.          *
  393.          *  Ist 'GemError () = TRUE', so liefert diese Funktion
  394.          *  den INTEGER-Wert, der von der zuletzt benutzten ROM-
  395.          *  Routine geliefert wurde, um den Fehler anzuzeigen.
  396.          *)
  397.  
  398. VAR ErrHdlProc: PROC;
  399.  
  400.         (*  Wird bei Auftreten eines Fehlers aufgerufen.
  401.          *  Die normalerweise hier installierte Routine tut nichts.
  402.          *  Wenn aber über die 'ErrorProc' der Fehler gemeldet wird,
  403.          *  kann hierüber herausgefunden werden, _wo_ der Fehler
  404.          *  auftrat.
  405.          *)
  406.  
  407.  
  408.                         (*   Nachfragefunktionen  *)
  409.                         (*   ===================  *)
  410.          
  411. PROCEDURE GEMAvailable (): BOOLEAN;
  412.  
  413.         (*  Erfragt, ob das GEM schon initalisiert ist.
  414.          *
  415.          *  Dies ist zum Beispiel bei Auto-Ordner-Programmen nicht der
  416.          *  Fall.
  417.          *  Solange diese Routine kein 'TRUE' liefert ist eine Anmeldung
  418.          *  mittels 'InitGem' sinnlos.
  419.          *)
  420.  
  421. PROCEDURE GDOSAvailable (): BOOLEAN;
  422.  
  423.         (*  Liefert 'TRUE', sobald ein GDOS-Treiber vorhanden ist.
  424.          *  Berücksichtigt auch das GEM 2.1 (liefert dort immer TRUE).
  425.          *)
  426.  
  427. PROCEDURE GEMVersion (): CARDINAL;
  428.  
  429.         (*  Liefert die Versionsnummer, die das GEM beim Anmelden einer
  430.          *  Applikation zurückgibt.
  431.          *
  432.          *  Das zuerst von Atari ausgelieferte TOS und das Blitter-TOS
  433.          *  liefern den Wert $120, das TOS 1.4 den Wert $140.
  434.          *
  435.          *  ACHTUNG: Damit diese Routine funktionieren kann muß die
  436.          *           Funktionsprozedur 'GemActive' den Wert 'TRUE'
  437.          *           liefern, also schon ein 'InitGem' durchgeführt
  438.          *           sein.
  439.          *)
  440.  
  441. PROCEDURE ApplicationID (): CARDINAL;
  442.  
  443.         (*  Liefert die GEM-Identifikationsnummer der aktuellen
  444.          *  GEM-Refrenz.
  445.          *)
  446.  
  447. PROCEDURE MaxPoints (): CARDINAL;
  448.  
  449.         (*  Liefert die maximale Anzahl der Punkte, die in einem Aufruf
  450.          *  von 'PolyLine', 'PolyMarker', etc. verarbeitet werden können.
  451.          *  Ein Wert von 0 bedeutet, daß die Anzahl nicht begrenzt ist.
  452.          *)
  453.          
  454.          
  455. (*   Jede der nachfolgenden Routinen erlaubtes einen Status abzufragen,
  456.  *   der für Module die ihrerseits andere GEM benutzende Module aufrufen
  457.  *   von Interesse sein kann. Ist z.B. 'NoUpdateWindow () # 0', so ist
  458.  *   es nicht möglich eine Menuzeile zu benutzen, man muß also erst die
  459.  *   entsprechende Anzahl von 'UpdateWindow (FALSE)' durchführen.
  460.  *)
  461.          
  462. PROCEDURE NoHideCursor (device: DeviceHandle): CARDINAL;
  463.  
  464.         (*  Liefert die Anzahl der 'HideCursor'-Aufrufe, die noch nicht
  465.          *  mit 'ShowCursor' rückgänig gemacht wurden.
  466.          *)
  467.  
  468. PROCEDURE NoGrafMouseOff (): CARDINAL;
  469.  
  470.         (*  Liefert die Anzahl der 'GrafMouse (mouseOff, NIL)'-Aufrufe,
  471.          *  die noch nicht mit 'GrafMouse (mouseOn, NIL)' rückgänig ge-
  472.          *  macht wurden.
  473.          *)
  474.  
  475. PROCEDURE NoUpdateWindow (): CARDINAL;
  476.  
  477.         (*  Liefert die Anzahl der 'UpdateWindow (TRUE)'-Aufrufe, die noch
  478.          *  nicht mit 'UpdateWindow (FALSE)' rückgänig gemacht wurden.
  479.          *)
  480.  
  481. PROCEDURE NoMouseControl (): CARDINAL;
  482.  
  483.         (*  Liefert die Anzahl der 'MouseControl (TRUE)-Aufrufe, die noch
  484.          *  nicht mit 'MouseControl (FALSE)' rückgänig gemacht wurden.
  485.          *)
  486.  
  487. PROCEDURE MouseInput (start: BOOLEAN);
  488.  
  489.         (*  Sorgt dafür, daß der Mauszeiger, unabhänig von seinem aktuellen
  490.          *  Zustand, sichtbar wird. Dies ist zum Beispiel vor dem Benutzen
  491.          *  einer Dialogbox sinnvoll.
  492.          *
  493.          *  TRUE  -- Der Mauszeiger wird sichtbar
  494.          *  FALSE -- Der Mauszeiger erhält seinen alten Status wieder
  495.          *
  496.          *  HINWEIS: Diese Routine sollte normallerweise nicht benutzt
  497.          *           werden. Sie ist systeminternen Funktionen vorbehalten.
  498.          *)
  499.  
  500.  
  501.  
  502. PROCEDURE SysInitGem (    sysKoor: CARDINAL;
  503.                       VAR handle : DeviceHandle;
  504.                       VAR success: BOOLEAN);
  505.  
  506. PROCEDURE SysInitApplication (VAR success: BOOLEAN);
  507.  
  508. END GEMEnv.